package org.openkoala.security.shiro.realm;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.cas.CasToken;
import org.apache.shiro.subject.PrincipalCollection;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidationException;
import org.jasig.cas.client.validation.TicketValidator;
import org.openkoala.security.facade.SecurityAccessFacade;
import org.openkoala.security.shiro.CurrentUser;
import org.openkoala.security.shiro.RoleHandle;
import org.openkoala.security.shiro.extend.ShiroFilterChainManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.dhcc.DRGsHosp.facade.LoginInfoFacade;
import com.dhcc.DRGsHosp.facade.dto.LoginInfoDTO;
/**
 * @Discription：    单点登录检验类
 * @Author：liuhongjun  
 * @ClassName: SecurityIntegrateCasRealm  
 * @Date: 2018年11月29日 下午9:04:38  
 * @Version：3.1.0 DHC.DRGs
 */
public class SecurityIntegrateCasRealm extends CasRealm implements RoleHandle   {

	private static final Logger LOGGER = LoggerFactory.getLogger(SecurityIntegrateCasRealm.class);
	
	@Inject
	private SecurityAccessFacade securityAccessFacade;

	@Inject
	private ShiroFilterChainManager shiroFilterChainManager;
	
	@Inject
	private LoginInfoFacade loginInfoFacade; 
	
	@SuppressWarnings("unused")
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		CasToken casToken = (CasToken) token;
        if (token == null) {
            return null;
        }
        
        String ticket = (String)casToken.getCredentials();
        if (!org.apache.shiro.util.StringUtils.hasText(ticket)) {
            return null;
        }        
        TicketValidator ticketValidator = ensureTicketValidator();        
        ShiroUser shiroUser = null;
        try {
            Assertion casAssertion = ticketValidator.validate(ticket, getCasService());
            AttributePrincipal casPrincipal = casAssertion.getPrincipal();
            String userId = casPrincipal.getName();
            LOGGER.debug("Validate ticket : {} in CAS server : {} to retrieve user : {}", new Object[]{
                    ticket, getCasServerUrlPrefix(), userId
            });
            Map<String, Object> attributes = casPrincipal.getAttributes();
            casToken.setUserId(userId);
            String rememberMeAttributeName = getRememberMeAttributeName();
            String rememberMeStringValue = (String)attributes.get(rememberMeAttributeName);
            boolean isRemembered = rememberMeStringValue != null && Boolean.parseBoolean(rememberMeStringValue);
            if (isRemembered) {
                casToken.setRememberMe(true);
            }
            
            List<Map<String, Object>> list=securityAccessFacade.getUserByUserId(userId);
            if(list.size()>0) {
            	Map<String, Object> map=list.get(0);
            	String name=map.get("NAME")==null?null:map.get("NAME").toString();
            	String email=map.get("EMAIL")==null?null:map.get("EMAIL").toString();
            	String telePhone=map.get("TELE_PHONE")==null?null:map.get("TELE_PHONE").toString();
            	String depCode=map.get("DEP_CODE")==null?null:map.get("DEP_CODE").toString();
            	String depDesc=map.get("DEP_DESC")==null?null:map.get("DEP_DESC").toString();
            	String wardCode=map.get("WARD_CODE")==null?null:map.get("WARD_CODE").toString();
             	String wardDesc=map.get("WARD_DESC")==null?null:map.get("WARD_DESC").toString();
            	String depYb=map.get("DEP_YB")==null?null:map.get("DEP_YB").toString();
                LoginInfoDTO loginDto= buildDtoCas(userId,name ,"1");
    			loginInfoFacade.creatLoginInfo(loginDto);
            	shiroUser = new ShiroUser(userId, name, email,telePhone,depCode, depDesc, depYb,wardCode,wardDesc);
            }
            SimpleAuthenticationInfo result = new SimpleAuthenticationInfo(shiroUser, ticket, getName());
            return result;
        } catch (TicketValidationException e) { 
	      	 e.printStackTrace();
	      	 LOGGER.error(e.getMessage());
	         SimpleAuthenticationInfo result = new SimpleAuthenticationInfo(shiroUser, ticket, getName());
	         return result;

      }
	}
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo result = new SimpleAuthorizationInfo();
		result.setRoles(shiroUser.getRoles());
		result.setStringPermissions(shiroUser.getPermissions());
		return result;
	}

	/**
	 * 切换角色
	 * 
	 * @param roleName
	 */
	public void switchOverRoleOfUser(String roleName) {
		PrincipalCollection principalCollection = CurrentUser.getPrincipals();
		ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();
		shiroUser.setRoleName(roleName);
		this.doGetAuthorizationInfo(principalCollection);
	}

	public void resetRoleName(String name) {
		switchOverRoleOfUser(name);
		shiroFilterChainManager.initFilterChain();
	}
	
	/**
	 * 
	 * @methodname :buildDto
	 * @description : 组装loginLogDto
	 * @param :
	 * @author :pcnicky
	 * @return :
	 * @date :2014年1月21日
	 */
	private LoginInfoDTO buildDtoCas(String userCode, String userName,String loginType) {
		LoginInfoDTO loginInfoDto = new LoginInfoDTO();
		loginInfoDto.setLoginId(UUID.randomUUID().toString());
		loginInfoDto.setLoginUserCode(userCode);
		loginInfoDto.setLoginUserName(userName);
		loginInfoDto.setLoginTime(new Date());
	
		// 获取客户端登录IP
		HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
		loginInfoDto.setLoginIp(getRemoteHost(request));
		// 登陆类型
		loginInfoDto.setLoginType(loginType);
	
		return loginInfoDto;
	}
	
	public String getRemoteHost(HttpServletRequest request){
	    String ip = request.getHeader("x-forwarded-for");
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("WL-Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getRemoteAddr();
	    }
	    return "0:0:0:0:0:0:0:1".equals(ip)?"127.0.0.1":ip;
	}
	
}
